
import unittest

class TestMapReduceFilter(unittest.TestCase):
    
    def test_filter(self):
        values = range(10)
        
        odds = filter(lambda x : x%2 == 1,values)
        self.assertEqual([1,3,5,7,9],odds)
        
        evens = filter(lambda x : x%2==0, values)
        self.assertEqual([0,2,4,6,8],evens)
        
    def test_filter_refactor(self):
        values = range(10)
        
        odds = [x for x in values if x%2==1]
        self.assertEqual([1,3,5,7,9],odds)
        
        evens = [x for x in values if x%2==0]
        self.assertEqual([0,2,4,6,8],evens)
        
    def test_map(self):
        # only requirement for argument is it must be iterable, no need to keep same type
        # here () is necessary to encapsulate (x+y,x-y), otherwise lambda will only recognize "x+y"
        results = map(lambda x,y: (x+y,x-y),(1,2,3),[4,5,9])
        self.assertEqual([(5,-3),(7,-3),(12,-6)],results)
        
    def test_reduce_no_init(self):
        self.assertEqual(10,reduce(lambda x,y: x+y,range(5)))
        
    def test_reduce_init(self):
        # if initial value is missing, first action happens on arguments[0] and arguments[1]
        self.assertEqual("helloworld ",reduce(lambda x,y: x+y+" ",("hello","world")))
        
        # if initial value is given, first action happens on that initial value and arguments[0]
        self.assertEqual("cheka said: hello world ",reduce(lambda x,y: x+y+" ",("hello","world"),"cheka said: "))
        
        
if __name__ == "__main__":
    unittest.main()